/** \brief File implementing a simple grid made of squares for the game of
 * life.
 *
 * This file contains the implementation of a class implementing a simple grid
 * for the game of life, where the cells are squares.
 *
 * @file GridBase.cpp
 * @author Johan "Solo" Luisier
 * @date 2013/03/22
 */
#include "SquareGrid.hpp"

#include "Cell.hpp"

#include <QtCore/QDebug>

const quint32 SquareGrid::MaxNeighbourNumber( 8u );

SquareGrid::SquareGrid( const quint32 &w, const quint32 &h, QObject *parent )
    : GridBase( w, h, parent )
{}

SquareGrid::~SquareGrid()
{}

bool SquareGrid::initialiseNeighbours()
{
    quint32 i, j;

    /**
     * First we take care of the inner rectangle having each 8 neighbours.
     */
    for ( i = 1u; i < height() - 1u; i++ )
    {
        for ( j = 1u; j < width() - 1u; j++ )
        {
            operator()( i, j ) -> addNeighbour( operator()( i - 1u, j ) );
            operator()( i, j ) -> addNeighbour( operator()( i, j - 1u ) );
            operator()( i, j ) -> addNeighbour( operator()( i + 1u, j ) );
            operator()( i, j ) -> addNeighbour( operator()( i, j + 1u ) );
            operator()( i, j ) -> addNeighbour( operator()( i - 1u, j -1u ) );
            operator()( i, j ) -> addNeighbour( operator()( i + 1u, j - 1u ) );
            operator()( i, j ) -> addNeighbour( operator()( i + 1u, j + 1u ) );
            operator()( i, j ) -> addNeighbour( operator()( i - 1u, j + 1u ) );
        }
    }

    j = width() - 1u;

    /**
     * Then we take care of the two vertical lines at the edges.
     */
    for ( i = 1u; i < height() - 1u; i++ )
    {
        operator()( i, 0u ) -> addNeighbour( operator()( i - 1u, 0u ) );
        operator()( i, 0u ) -> addNeighbour( operator()( i + 1u, 0u ) );
        operator()( i, 0u ) -> addNeighbour( operator()( i , 1u ) );
        operator()( i, 0u ) -> addNeighbour( operator()( i - 1u, 1u ) );
        operator()( i, 0u ) -> addNeighbour( operator()( i + 1u, 1u ) );


        operator()( i, j ) -> addNeighbour( operator()( i - 1u, j ) );
        operator()( i, j ) -> addNeighbour( operator()( i + 1u, j ) );
        operator()( i, j ) -> addNeighbour( operator()( i, j - 1u ) );
        operator()( i, j ) -> addNeighbour( operator()( i - 1u, j - 1u ) );
        operator()( i, j ) -> addNeighbour( operator()( i + 1u, j - 1u ) );
    }

    i = height() - 1u;

    /**
     * Then we take care of the two horizontal lines at the edges.
     */
    for ( j = 1u; j < width() - 1u; j++ )
    {
        operator()( 0u, j ) -> addNeighbour( operator()( 0u, j - 1u ) );
        operator()( 0u, j ) -> addNeighbour( operator()( 1u, j ) );
        operator()( 0u, j ) -> addNeighbour( operator()( 0u, j + 1u ) );
        operator()( 0u, j ) -> addNeighbour( operator()( 1u, j + 1u ) );
        operator()( 0u, j ) -> addNeighbour( operator()( 1u, j - 1u) );


        operator()( i, j ) -> addNeighbour( operator()( i, j - 1u ) );
        operator()( i, j ) -> addNeighbour( operator()( i - 1u, j ) );
        operator()( i, j ) -> addNeighbour( operator()( i, j + 1u ) );
        operator()( i, j ) -> addNeighbour( operator()( i - 1u, j + 1u ) );
        operator()( i, j ) -> addNeighbour( operator()( i - 1u, j - 1u ) );
    }

    /**
     * Finally the four corners.
     */
    operator()( 0u, 0u ) -> addNeighbour( operator()( 1u, 0u ) );
    operator()( 0u, 0u ) -> addNeighbour( operator()( 0u, 1u ) );
    operator()( 0u, 0u ) -> addNeighbour( operator()( 1u, 1u ) );

    operator()( height() - 1u, 0u ) -> addNeighbour( operator()( height() - 1u, 1u ) );
    operator()( height() - 1u, 0u ) -> addNeighbour( operator()( height() - 2u, 0u ) );
    operator()( height() - 1u, 0u ) -> addNeighbour( operator()( height() - 2u, 1u ) );

    operator()( 0u, width() - 1u ) -> addNeighbour( operator()( 1u, width() - 1u ) );
    operator()( 0u, width() - 1u ) -> addNeighbour( operator()( 0u, width() - 2u ) );
    operator()( 0u, width() - 1u ) -> addNeighbour( operator()( 1u, width() - 2u ) );

    operator()( height() - 1u, width() - 1u ) -> addNeighbour( operator()( height() - 1u, width() - 2u ) );
    operator()( height() - 1u, width() - 1u ) -> addNeighbour( operator()( height() - 2u, width() - 1u ) );
    operator()( height() - 1u, width() - 1u ) -> addNeighbour( operator()( height() - 2u, width() - 2u ) );

    for ( i = 0u; i < height(); i++ )
    {
        for ( j = 0u; j < width(); j++ )
        {
            operator()( i, j ) -> setLifeRules( GameRules );
//            operator()( i, j ) -> setBirthConditions( BirthConditions );
//            operator()( i, j ) -> setSurvivalConditions( SurvivalConditions );
        }
    }

    qDebug() << tr( "SquareGrid::initialiseNeighbours specific initialisation done" );

    CellNumber = width() * height();

    return true;
}
